package mitchellcam1;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Scanner;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.GoogleApi;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;

public class LatitudeUser
{	
	public boolean[] privacyArray;
	public boolean[] zoneControlArray;
	public boolean[] inZone;
	String userID;
	int choice;
	String authorizeURL= null;
	String protectedResourceURL= null;
	String cityProtectedResourceURL = null;
	String apiKey= null;
	String apiSecret= null;
	double currenttoken;
	double latitude;
	double longitude;
	Token oAuthToken = null;
	OAuthService latitudeservice = null;
	int counter;
	String justToken = null;
	String justSecret = null;
	int counterb;
	String city = null;
	boolean fresh;
	boolean freshNotify = true;
	double latitudeAge = 0;
	String currentString;
	String rawLatitudeResponse;

	public LatitudeUser()
	{
		setUserID("");
	}
	public LatitudeUser(String userID)
	{
		setUserID(userID);
	}
	public void setUserID(String userID)
	{
		this.userID = userID;
	}
	public void setup(int mainChoice,String incomingUserID,int workingUser, int cameraCount, int zoneCount, LatitudeUser[] userArray, IpCam[] cameraArray, Zone[] zoneArray)
	{
		//create privacy and zone privacy arrays
		privacyArray = new boolean[cameraCount];
		zoneControlArray = new boolean[zoneCount];
		inZone = new boolean[zoneCount];
		
		userID = incomingUserID;
		
		if (userID.equals("null"))
		{
			//receive user ID
			System.out.printf("\nInput user %d ID:",(workingUser + 1));
			Scanner in = new Scanner(System.in);
			userID = in.next();
			
			//find out if this is a saved user
			System.out.println("Is this a previous user you want to import from a text file?");
			System.out.println("1.Yes");
			System.out.println("2.No");
			in = new Scanner(System.in);
			choice = in.nextInt();
		}
		else
		{
			userID = incomingUserID;
			choice = 1;
		}
		
		if (choice == 2)
		{
			try
			{
				//receive authorizeURL
				System.out.println("\nInput authorizeURL");
				Scanner in = new Scanner(System.in);
				authorizeURL = in.next();
				
				//receive protectedResourceURL
				System.out.println("\nInput protectedResourceURL");
				in = new Scanner(System.in);
				protectedResourceURL = in.next();
				
				//receive apiKey
				System.out.println("\nInput apiKey");
				in = new Scanner(System.in);
				apiKey = in.next();
				
				//receive apiSecret
				System.out.println("\nInput apiSecret");
				in = new Scanner(System.in);
				apiSecret = in.next();
				
				//create the OAuth service from scratch
				establishOAuth(cameraCount);
				
				//configure cameras for this user
				configureCameras(cameraCount, privacyArray, userArray, cameraArray);
				
				//configure zones for this user
				configureZones(zoneCount, privacyArray, userArray, zoneArray);
				
				//write user info to a file
				new File(userID + ".log");
				new File(userID + ".user");
				FileOutputStream outputstream = new FileOutputStream(userID +".user");
				PrintWriter fileWriter = new PrintWriter(outputstream);
				fileWriter.print(authorizeURL+"\n");
				fileWriter.print(protectedResourceURL+"\n");
				fileWriter.print(apiKey+"\n");
				fileWriter.print(apiSecret+"\n");
				fileWriter.print(oAuthToken.getToken()+"\n");
				fileWriter.print(oAuthToken.getSecret()+"\n");
				fileWriter.print(cityProtectedResourceURL+"\n");
				fileWriter.close();
			}
			catch (FileNotFoundException e) 
			{
				e.printStackTrace();
			}		
		}
		if (choice == 1)
		{
			//read user info from the appropriate file
			try
			{
			    // Open the file that is the first 
			    // command line parameter
			    FileInputStream fstream = new FileInputStream(userID + ".user");
			    // Get the object of DataInputStream
			    DataInputStream stream = new DataInputStream(fstream);
			    BufferedReader br = new BufferedReader(new InputStreamReader(stream));
			    String strLine;
			    //Read File Line By Line
			    counter = 1;
			    while ((strLine = br.readLine()) != null)   
			    {
			      switch (counter)
			      {
			      	case 1: authorizeURL = strLine;
			      			break;
			      			
			      	case 2: protectedResourceURL = strLine;
			      			break;
			      			
			      	case 3: apiKey = strLine;
			      			break;
			      			
			      	case 4: apiSecret = strLine;
			      			break;
			      			
			      	case 5: justToken = strLine;
			      			break;
			      			
			      	case 6: justSecret = strLine;
			      			break;
			      	
			      	case 7: cityProtectedResourceURL = strLine;
			      			break;
			      }
			      counter++;
			    }
			    //Close the input stream
			    stream.close();
			    
				//build OAuth Service with Scribe
				latitudeservice = new ServiceBuilder()
				.provider(GoogleApi.class)
				.apiKey(apiKey)
				.apiSecret(apiSecret)
				.scope("https://www.googleapis.com/auth/latitude")
				.build();
			    
			    //form the token
			    oAuthToken = new Token(justToken,justSecret);

			}
			catch(Exception e)
			{
				System.out.println("User file non-existent or otherwise no-good!");
				e.printStackTrace();
			}
			
			if (mainChoice == 1)
			{
				//restore cameras for this user
				try
				{
				    // Open the file that is the first 
				    // command line parameter
				    FileInputStream fstream = new FileInputStream(userID + ".cameras.config");
				    // Get the object of DataInputStream
				    DataInputStream stream = new DataInputStream(fstream);
				    BufferedReader br = new BufferedReader(new InputStreamReader(stream));
				    String strLine;
				    //Read File Line By Line
				    int counter = 0;
				    while ((strLine = br.readLine()) != null)   
				    {
						if (Integer.parseInt(strLine) == 1)
						{
							privacyArray[counter] = true;
						}
						else
						{
							privacyArray[counter] = false;
						}
						counter++;
				    }
				    //Close the input stream
				    stream.close();
				   
				}
				catch(Exception e)
				{
					System.out.println("Camera file non-existent or otherwise no-good!");
					e.printStackTrace();
				}
				
				//restore zones for this user
				try
				{
				    // Open the file that is the first 
				    // command line parameter
				    FileInputStream fstream = new FileInputStream(userID + ".zones.config");
				    // Get the object of DataInputStream
				    DataInputStream stream = new DataInputStream(fstream);
				    BufferedReader br = new BufferedReader(new InputStreamReader(stream));
				    String strLine;
				    //Read File Line By Line
				    int counter = 0;
				    while ((strLine = br.readLine()) != null)   
				    {
						if (Integer.parseInt(strLine) == 1)
						{
							zoneControlArray[counter] = true;
						}
						else
						{
							zoneControlArray[counter] = false;
						}
						counter++;
				    }
				    //Close the input stream
				    stream.close();
				   
				}
				catch(Exception e)
				{
					System.out.println("Camera file non-existent or otherwise no-good!");
					e.printStackTrace();
				}
			}
			else
			{
				//configure cameras for this user
				configureCameras(cameraCount, privacyArray, userArray, cameraArray);
				
				//configure zones for this user
				configureZones(zoneCount, zoneControlArray, userArray, zoneArray);
			}
		}
	}
	public void establishOAuth(int cameraCount)
	{
		//build OAuth Service with Scribe
		latitudeservice = new ServiceBuilder()
		.provider(GoogleApi.class)
		.apiKey(apiKey)
		.apiSecret(apiSecret)
		.scope("https://www.googleapis.com/auth/latitude")
		.build();
		
		// Obtain User's Request Token
		Token requestToken = latitudeservice.getRequestToken();			
		System.out.println();
		System.out.println("Authorize here:");
		System.out.print(" ");
		System.out.println(authorizeURL + requestToken.getToken());
		System.out.println();
		System.out.println("And paste the verifier here");
		System.out.print(">>");
		Scanner verifierin = new Scanner(System.in);
		Verifier verifier = new Verifier(verifierin.nextLine());
	
		// Trade the Request Token and Verifier for the Access Token
		oAuthToken = latitudeservice.getAccessToken(requestToken, verifier);
	}
	public void configureCameras(int cameraCount, boolean[] privacyArray,LatitudeUser[] userArray, IpCam[] cameraArray)
	{
		System.out.println("\n");
		//go through each camera for the working user and set the privacy preferences
		
		try
		{
			new File(userID+".cameras.config");
			FileOutputStream outputstream = new FileOutputStream(userID+".cameras.config");
			PrintWriter fileWriter = new PrintWriter(outputstream);
			int should = 0;
			for (int counterb = 0 ; counterb < cameraArray.length ; counterb++)
			{
				//Privacy mode determination
				System.out.printf("\nShould %s's presence determine %s's privacy mode?\n",userID,cameraArray[counterb].cameraID);
				System.out.println("1.yes");
				System.out.println("2.no");
				Scanner in = new Scanner(System.in);
				should = in.nextInt();
				if (should==1)
				{
					privacyArray[counterb] = true;
				}
				else
				{
					privacyArray[counterb] = false;
				}
				fileWriter.print(should+"\n");
			}
			fileWriter.close();
		}
		catch (FileNotFoundException e) 
		{
			e.printStackTrace();
		}
	}	
	public void configureZones(int zoneCount, boolean[] privacyArray,LatitudeUser[] userArray, Zone[] zoneArray)
	{
		System.out.println("\n");
		//go through each zone for the working user and set the privacy preferences

		try
		{
			new File(userID+".zones.config");
			FileOutputStream outputstream = new FileOutputStream(userID+".zones.config");
			PrintWriter fileWriter = new PrintWriter(outputstream);
			int should = 0;
			for (int counterb = 0 ; counterb < zoneArray.length ; counterb++)
			{
				//Privacy mode determination
				System.out.printf("\nShould %s's presence control zone %s?\n",userID,zoneArray[counterb].zoneId);
				System.out.println("1.yes");
				System.out.println("2.no");
				Scanner in = new Scanner(System.in);
				should = in.nextInt();
				if (should==1)
				{
					zoneControlArray[counterb] = true;
				}
				else
				{
					zoneControlArray[counterb] = false;
				}
				fileWriter.print(should+"\n");
			}
			fileWriter.close();
		}
		catch (FileNotFoundException e) 
		{
			e.printStackTrace();
		}
	}
	public void getLocation(Calendar cal,int freshSecs)
	{
        // Get Latitude response
        OAuthRequest request = new OAuthRequest(Verb.GET, protectedResourceURL);
        latitudeservice.signRequest(oAuthToken, request);
        request.addHeader("GData-Version", "3.0");
        
        rawLatitudeResponse = request.send().getBody();
        
        //read for latitude and longitude
        	StringReader latitudereader = new StringReader(rawLatitudeResponse);
	        
	        //skip 77 columns
	        try 
	        {
	                latitudereader.skip(77);
	        } 
	        catch (IOException e) 
	        {
	                e.printStackTrace();
	        }
	                
	        //tokenize latitude, longitude        
	        StreamTokenizer st = new StreamTokenizer(latitudereader);
	        st.parseNumbers();
	        int tokenizercounter = 1;
	        try 
	        {
	                while (st.nextToken() != StreamTokenizer.TT_EOF)
	                {
	                        if (st.ttype == StreamTokenizer.TT_NUMBER)
	                        {
	                                currenttoken = st.nval;
	                                if (tokenizercounter == 1)
	                                {
	                                        latitude = currenttoken;
	                                }
	                                if (tokenizercounter == 2)
	                                {
	                                        longitude = currenttoken;
	                                }
	                                tokenizercounter++;
	                        }
	                }
	        } 
	        catch (IOException e1) 
	        {
	                System.out.println("there was a problem");
	                e1.printStackTrace();
	        }
		
        //read for age of latitude data
        	latitudereader = new StringReader(rawLatitudeResponse);
	        
	        //skip 51 columns
	        try 
	        {
	                latitudereader.skip(51);
	        } 
	        catch (IOException e) 
	        {
	                e.printStackTrace();
	        }
	                
	        //tokenize age   
	        st = new StreamTokenizer(latitudereader);
	        st.parseNumbers();
	        tokenizercounter = 1;
	        try 
	        {
	                while (st.nextToken() != StreamTokenizer.TT_EOF)
	                {
	                        if (st.ttype == StreamTokenizer.TT_NUMBER)
	                        {
	                                currenttoken = st.nval;
	                                if (tokenizercounter == 1)
	                                {
	                                		cal = Calendar.getInstance();
	                                		latitudeAge = (cal.getTimeInMillis() - currenttoken)/60000;
	                                }
	                                tokenizercounter++;
	                        }
	                }
	        } 
	        catch (IOException e1) 
	        {
	                System.out.println("there was a problem");
	                e1.printStackTrace();
	        }    
	        
		//calculate whether or not the user is fresh and whether the user has already been notified of it
		    //if the user is fresh but isn't marked so
		    if (freshSecs > latitudeAge && fresh == false)
			{
				freshNotify = false;
				fresh = true;
			}
		    //if the user is stale but isn't marked so
		    if (freshSecs < latitudeAge && fresh == true)
			{
				freshNotify = false;
				fresh = false;
			}
	}
	public double getDistance(double pointLongitude, double pointLatitude)
	{
		return (Math.sqrt((Math.pow((Math.abs(latitude - pointLatitude)),2) + (Math.pow(Math.abs(longitude - pointLongitude),2)))));
	}
	public void logLocation()
	{
//		getCity();
		try
		{
			String outputstream = (userID +".log");
			boolean append = true;
			PrintWriter fileWriter = new PrintWriter(new FileWriter(outputstream,append));
			fileWriter.println(new Timestamp(System.currentTimeMillis()));
//			fileWriter.println("City: "+city);
			fileWriter.println(latitude);
			fileWriter.println(longitude);
			fileWriter.println();
			fileWriter.close();
		}
		catch (IOException e1)
		{
			System.out.println("Couldn't log!");
		}
	}
	public void logLeave(String zone)
	{
		try
		{
			String outputstream = (userID +".log");
			boolean append = true;
			PrintWriter fileWriter = new PrintWriter(new FileWriter(outputstream,append));
			fileWriter.println(new Timestamp(System.currentTimeMillis()));
			fileWriter.println("user left " + zone);
			fileWriter.println();
			fileWriter.close();
		}
		catch (IOException e1)
		{
			System.out.println("Couldn't log!");
		}
	}
	public void logEnter(String zone)
	{
		try
		{
			String outputstream = (userID +".log");
			boolean append = true;
			PrintWriter fileWriter = new PrintWriter(new FileWriter(outputstream,append));
			fileWriter.println(new Timestamp(System.currentTimeMillis()));
			fileWriter.println("user entered " + zone);
			fileWriter.println();
			fileWriter.close();
		}
		catch (IOException e1)
		{
			System.out.println("Couldn't log!");
		}
	}

	public void getCity()
	{
		// Get Latitude response
		OAuthRequest request = new OAuthRequest(Verb.GET, cityProtectedResourceURL);
		latitudeservice.signRequest(oAuthToken, request);
		request.addHeader("GData-Version", "3.0");
		
		city = request.send().getBody();
	}
}